/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.folderit.apps.rooms;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.test.AndroidTestCase;
import android.util.Log;

import com.folderit.apps.rooms.data.RoomsContract.ReservationEntry;
import com.folderit.apps.rooms.data.RoomsContract.RoomEntry;
import com.folderit.apps.rooms.data.RoomsContract.UserEntry;
import com.folderit.apps.rooms.data.RoomsDbHelper;

import java.util.Map;
import java.util.Set;

public class TestDb extends AndroidTestCase {

    public static final String LOG_TAG = TestDb.class.getSimpleName();

    public void testCreateDb() throws Throwable {
        mContext.deleteDatabase(RoomsDbHelper.DATABASE_NAME);
        SQLiteDatabase db = new RoomsDbHelper(this.mContext).getWritableDatabase();
        assertEquals(true, db.isOpen());
        db.close();
    }

    public void testInsertReadDb() {

        // If there's an error in those massive SQL table creation Strings,
        // errors will be thrown here when you try to get a writable database.
        RoomsDbHelper dbHelper = new RoomsDbHelper(mContext);
        SQLiteDatabase db = dbHelper.getWritableDatabase();

        /** User **/
        ContentValues userTestValues = createUserValues();

        long userRowId;
        userRowId = db.insert(UserEntry.TABLE_NAME, null, userTestValues);

        // Verify we got a row back.
        assertTrue(userRowId != -1);
        Log.d(LOG_TAG, "New user row id: " + userRowId);

        // Data's inserted.  IN THEORY.  Now pull some out to stare at it and verify it made
        // the round trip.

        // A cursor is your primary interface to the query results.
        Cursor cursor = db.query(
                UserEntry.TABLE_NAME,  // Table to Query
                null, // all columns
                null, // Columns for the "where" clause
                null, // Values for the "where" clause
                null, // columns to group by
                null, // columns to filter by row groups
                null // sort order
        );

        validateCursor(cursor, userTestValues);

        /** Room **/
        ContentValues roomTestValues = createRoomValues();

        long roomRowId;
        roomRowId = db.insert(RoomEntry.TABLE_NAME, null, roomTestValues);

        // Verify we got a row back.
        assertTrue(roomRowId != -1);
        Log.d(LOG_TAG, "New room row id: " + roomRowId);

        // A cursor is your primary interface to the query results.
        Cursor roomCursor = db.query(
                RoomEntry.TABLE_NAME,  // Table to Query
                null, // all columns
                null, // Columns for the "where" clause
                null, // Values for the "where" clause
                null, // columns to group by
                null, // columns to filter by row groups
                null // sort order
        );

        validateCursor(roomCursor, roomTestValues);

        /** Reservation **/
        ContentValues reservationValues = createReservationValues(userRowId, roomRowId);

        long reservationRowId = db.insert(ReservationEntry.TABLE_NAME, null, reservationValues);
        assertTrue(reservationRowId != -1);

        // A cursor is your primary interface to the query results.
        Cursor reservationCursor = db.query(
                ReservationEntry.TABLE_NAME,  // Table to Query
                null, // leaving "columns" null just returns all the columns.
                null, // cols for "where" clause
                null, // values for "where" clause
                null, // columns to group by
                null, // columns to filter by row groups
                null  // sort order
        );

        validateCursor(reservationCursor, reservationValues);

        dbHelper.close();
    }

    static ContentValues createReservationValues(long userRowId, long roomRowId) {
        ContentValues testValues = new ContentValues();
        testValues.put(ReservationEntry.COLUMN_ROOM_KEY, roomRowId);
        testValues.put(ReservationEntry.COLUMN_USER_KEY, userRowId);
        testValues.put(ReservationEntry.COLUMN_CREATED, "20141216211201");
        testValues.put(ReservationEntry.COLUMN_BEGIN, "20141216211201");
        testValues.put(ReservationEntry.COLUMN_END, "20141216211201");
        testValues.put(ReservationEntry.COLUMN_EXTERNAL_ID, 123);
        testValues.put(ReservationEntry.COLUMN_EVENT_TITLE, "A meeting with some people");

        return testValues;
    }

    static ContentValues createUserValues() {
        // Create a new map of values, where column names are the keys
        ContentValues testValues = new ContentValues();
        testValues.put(UserEntry.COLUMN_NAME, "John Smith");
        testValues.put(UserEntry.COLUMN_PHONE_NUMBER, "+5493424772512");
        testValues.put(UserEntry.COLUMN_EMAIL, "johnsmith@domain.com");

        return testValues;
    }

    static ContentValues createRoomValues() {
        ContentValues testValues = new ContentValues();
        testValues.put(RoomEntry.COLUMN_ROOM_NAME, "Big Room");
        testValues.put(RoomEntry.COLUMN_DESCRIPTION, "Big Room in front building first floor");
        testValues.put(RoomEntry.COLUMN_COLOR_ID, 1);
        testValues.put(RoomEntry.COLUMN_EXTERNAL_ID, 2);

        return testValues;
    }

    static void validateCursor(Cursor valueCursor, ContentValues expectedValues) {

        assertTrue(valueCursor.moveToFirst());

        Set<Map.Entry<String, Object>> valueSet = expectedValues.valueSet();
        for (Map.Entry<String, Object> entry : valueSet) {
            String columnName = entry.getKey();
            int idx = valueCursor.getColumnIndex(columnName);
            assertFalse(idx == -1);
            String expectedValue = entry.getValue().toString();
            assertEquals(expectedValue, valueCursor.getString(idx));
        }
        valueCursor.close();
    }
}
